bitkeeper revision 1.259.4.1 (3f0bed4cJB9LOOhEpc2nIhwKM2NwAA)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 9 Jul 2003 10:24:12 +0000 (10:24 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 9 Jul 2003 10:24:12 +0000 (10:24 +0000)
ioremap.c:
  new file
mkbuildtree, Makefile, dom0_memory.c:
  ioremap support in Xenolinux.
.del-io.h~441bb6eed5f4a3f5:
  Delete: xenolinux-2.4.21-sparse/include/asm-xeno/io.h

.rootkeys
xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_memory.c
xenolinux-2.4.21-sparse/arch/xeno/mm/Makefile
xenolinux-2.4.21-sparse/arch/xeno/mm/ioremap.c [new file with mode: 0644]
xenolinux-2.4.21-sparse/include/asm-xeno/io.h [deleted file]
xenolinux-2.4.21-sparse/mkbuildtree

index 684ca66f3939c3b14ff3d8715b8eb53dc968a343..08bac65889587d521227d382f4d749fe6afae342 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3e5a4e66TyNNUEXkr5RxqvQhXK1MQA xenolinux-2.4.21-sparse/arch/xeno/mm/get_unmapped_area.c
 3e5a4e668SE9rixq4ahho9rNhLUUFQ xenolinux-2.4.21-sparse/arch/xeno/mm/hypervisor.c
 3e5a4e661gLzzff25pJooKIIWe7IWg xenolinux-2.4.21-sparse/arch/xeno/mm/init.c
+3f0bed43UUdQichXAiVNrjV-y2Kzcg xenolinux-2.4.21-sparse/arch/xeno/mm/ioremap.c
 3e5a4e66qRlSTcjafidMB6ulECADvg xenolinux-2.4.21-sparse/arch/xeno/vmlinux.lds
 3ea53c6em6uzVHSiGqrbbAVofyRY_g xenolinux-2.4.21-sparse/drivers/block/genhd.c
 3e5a4e66mrtlmV75L1tjKDg8RaM5gA xenolinux-2.4.21-sparse/drivers/block/ll_rw_blk.c
 3e5a4e67w_DWgjIJ17Tlossu1LGujQ xenolinux-2.4.21-sparse/include/asm-xeno/highmem.h
 3e5a4e67YtcyDLQsShhCfQwPSELfvA xenolinux-2.4.21-sparse/include/asm-xeno/hw_irq.h
 3e5a4e677VBavzM1UZIEcH1B-RlXMA xenolinux-2.4.21-sparse/include/asm-xeno/hypervisor.h
-3e5a4e67Ulv-Ll8Zp4j2GwMwQ8aAXQ xenolinux-2.4.21-sparse/include/asm-xeno/io.h
 3e5a4e673p7PEOyHFm3nHkYX6HQYBg xenolinux-2.4.21-sparse/include/asm-xeno/irq.h
 3ead095db_LRUXnxaqs0dA1DWhPoQQ xenolinux-2.4.21-sparse/include/asm-xeno/keyboard.h
 3e5a4e67zoNch27qYhEBpr2k6SABOg xenolinux-2.4.21-sparse/include/asm-xeno/mmu.h
index 7f28b37df64259cb399cab522e75fbd765147d53..f36ac583c4daa626d1f8060fab1b9680561c1931 100644 (file)
 #define MAP_DISCONT 1
 
 extern struct list_head * find_direct(struct list_head *, unsigned long);
-
-/*
- * bd240: functions below perform direct mapping to the real physical pages
- * needed for mapping various hypervisor specific structures needed in dom0
- * userspace by various management applications such as domain builder etc.
- */
-
-#define direct_set_pte(pteptr, pteval) queue_l1_entry_update(__pa(pteptr)|PGREQ_UNCHECKED_UPDATE, (pteval).pte_low)
-
-#define direct_pte_clear(pteptr) queue_l1_entry_update(__pa(pteptr)|PGREQ_UNCHECKED_UPDATE, 0)
-
-#define __direct_pte(x) ((pte_t) { (x) } )
-#define __direct_mk_pte(page_nr,pgprot) __direct_pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot))
-#define direct_mk_pte_phys(physpage, pgprot)   __direct_mk_pte((physpage) >> PAGE_SHIFT, pgprot)
-
-static inline void forget_pte(pte_t page)
-{
-    if (!pte_none(page)) {
-        printk("forget_pte: old mapping existed!\n");
-        BUG();
-    }
-}
-
-static inline void direct_remappte_range(pte_t * pte, unsigned long address, unsigned long size,
-                                         unsigned long phys_addr, pgprot_t prot)
-{
-    unsigned long end;
-
-    address &= ~PMD_MASK;
-    end = address + size;
-    if (end > PMD_SIZE)
-        end = PMD_SIZE;
-    do {
-        pte_t oldpage;
-        oldpage = ptep_get_and_clear(pte);
-
-        direct_set_pte(pte, direct_mk_pte_phys(phys_addr, prot));
-
-        forget_pte(oldpage);
-        address += PAGE_SIZE;
-        phys_addr += PAGE_SIZE;
-        pte++;
-    } while (address && (address < end));
-
-}
-
-static inline int direct_remappmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
-                                        unsigned long phys_addr, pgprot_t prot)
-{
-    unsigned long end;
-
-    address &= ~PGDIR_MASK;
-    end = address + size;
-    if (end > PGDIR_SIZE)
-        end = PGDIR_SIZE;
-    phys_addr -= address;
-    do {
-        pte_t * pte = pte_alloc(mm, pmd, address);
-        if (!pte)
-            return -ENOMEM;
-        direct_remappte_range(pte, address, end - address, address + phys_addr, prot);
-        address = (address + PMD_SIZE) & PMD_MASK;
-        pmd++;
-    } while (address && (address < end));
-    return 0;
-}
-
-/*  Note: this is only safe if the mm semaphore is held when called. */
-int direct_remap_page_range(unsigned long from, unsigned long phys_addr, unsigned long size, pgprot_t prot)
-{
-    int error = 0;
-    pgd_t * dir;
-    unsigned long beg = from;
-    unsigned long end = from + size;
-    struct mm_struct *mm = current->mm;
-
-    phys_addr -= from;
-    dir = pgd_offset(mm, from);
-    flush_cache_range(mm, beg, end);
-    if (from >= end)
-        BUG();
-
-    spin_lock(&mm->page_table_lock);
-    do {
-        pmd_t *pmd = pmd_alloc(mm, dir, from);
-        error = -ENOMEM;
-        if (!pmd)
-            break;
-        error = direct_remappmd_range(mm, pmd, from, end - from, phys_addr + from, prot);
-        if (error)
-            break;
-        from = (from + PGDIR_SIZE) & PGDIR_MASK;
-        dir++;
-    } while (from && (from < end));
-    spin_unlock(&mm->page_table_lock);
-    flush_tlb_range(mm, beg, end);
-    return error;
-}
+extern int direct_remap_area_pages(struct mm_struct *, unsigned long, 
+                                   unsigned long, unsigned long, pgprot_t);
+extern void direct_zap_page_range(struct mm_struct *, unsigned long, 
+                                  unsigned long);
 
 /* 
  * used for remapping discontiguous bits of domain's memory, pages to map are
  * found from frame table beginning at the given first_pg index
  */ 
 int direct_remap_disc_page_range(unsigned long from, 
-                                 unsigned long first_pg, int tot_pages, pgprot_t prot)
+                                 unsigned long first_pg, 
+                                 int tot_pages, 
+                                 pgprot_t prot)
 {
     dom0_op_t dom0_op;
-    unsigned long *pfns = get_free_page(GFP_KERNEL);
+    unsigned long *pfns = (unsigned long *)get_free_page(GFP_KERNEL);
     unsigned long start = from;
     int pages, i;
 
@@ -145,7 +53,8 @@ int direct_remap_disc_page_range(unsigned long from,
 
         for ( i = 0; i < pages; i++ )
         {
-            if(direct_remap_page_range(start, pfns[i] << PAGE_SHIFT, 
+            if(direct_remap_area_pages(current->mm,
+                                       start, pfns[i] << PAGE_SHIFT, 
                                        PAGE_SIZE, prot))
                 goto out;
             start += PAGE_SIZE;
@@ -154,15 +63,10 @@ int direct_remap_disc_page_range(unsigned long from,
     }
 
  out:
-    free_page(pfns);
+    free_page((unsigned long)pfns);
     return tot_pages;
 } 
            
-/* below functions replace standard sys_mmap and sys_munmap which are absolutely useless
- * for direct memory mapping. direct_zap* functions are minor ammendments to the 
- * original versions in mm/memory.c. the changes are to enable unmapping of real physical
- * addresses.
- */
 
 unsigned long direct_mmap(unsigned long phys_addr, unsigned long size, 
                           pgprot_t prot, int flag, int tot_pages)
@@ -202,7 +106,8 @@ unsigned long direct_mmap(unsigned long phys_addr, unsigned long size,
         ret = direct_remap_disc_page_range(addr, phys_addr >> PAGE_SHIFT, 
                                            tot_pages, prot);
     } else {
-        ret = direct_remap_page_range(addr, phys_addr, size, prot);
+        ret = direct_remap_area_pages(current->mm, 
+                                      addr, phys_addr, size, prot);
     }
 
     if(ret == 0)
@@ -212,104 +117,6 @@ unsigned long direct_mmap(unsigned long phys_addr, unsigned long size,
     return ret;
 }
 
-/* most of the checks, refcnt updates, cache stuff have been thrown out as they are not
- * needed
- */
-static inline int direct_zap_pte_range(mmu_gather_t *tlb, pmd_t * pmd, unsigned long address, 
-                                       unsigned long size)
-{
-    unsigned long offset;
-    pte_t * ptep;
-    int freed = 0;
-
-    if (pmd_none(*pmd))
-        return 0;
-    if (pmd_bad(*pmd)) {
-        pmd_ERROR(*pmd);
-        pmd_clear(pmd);
-        return 0;
-    }
-    ptep = pte_offset(pmd, address);
-    offset = address & ~PMD_MASK;
-    if (offset + size > PMD_SIZE)
-        size = PMD_SIZE - offset;
-    size &= PAGE_MASK;
-    for (offset=0; offset < size; ptep++, offset += PAGE_SIZE) {
-        pte_t pte = *ptep;
-        if (pte_none(pte))
-            continue;
-        freed ++;
-        direct_pte_clear(ptep);
-    }
-
-    return freed;
-}
-
-static inline int direct_zap_pmd_range(mmu_gather_t *tlb, pgd_t * dir, 
-                                       unsigned long address, unsigned long size)
-{
-    pmd_t * pmd;
-    unsigned long end;
-    int freed;
-
-    if (pgd_none(*dir))
-        return 0;
-    if (pgd_bad(*dir)) {
-        pgd_ERROR(*dir);
-        pgd_clear(dir);
-        return 0;
-    }
-    pmd = pmd_offset(dir, address);
-    end = address + size;
-    if (end > ((address + PGDIR_SIZE) & PGDIR_MASK))
-        end = ((address + PGDIR_SIZE) & PGDIR_MASK);
-    freed = 0;
-    do {
-        freed += direct_zap_pte_range(tlb, pmd, address, end - address);
-        address = (address + PMD_SIZE) & PMD_MASK; 
-        pmd++;
-    } while (address < end);
-    return freed;
-}
-
-/*
- * remove user pages in a given range.
- */
-void direct_zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size)
-{
-    mmu_gather_t *tlb;
-    pgd_t * dir;
-    unsigned long start = address, end = address + size;
-    int freed = 0;
-
-    dir = pgd_offset(mm, address);
-
-    /*
-     * This is a long-lived spinlock. That's fine.
-     * There's no contention, because the page table
-     * lock only protects against kswapd anyway, and
-     * even if kswapd happened to be looking at this
-     * process we _want_ it to get stuck.
-     */
-    if (address >= end)
-        BUG();
-    spin_lock(&mm->page_table_lock);
-    flush_cache_range(mm, address, end);
-    tlb = tlb_gather_mmu(mm);
-
-    do {
-        freed += direct_zap_pmd_range(tlb, dir, address, end - address);
-        address = (address + PGDIR_SIZE) & PGDIR_MASK;
-        dir++;
-    } while (address && (address < end));
-
-    /* this will flush any remaining tlb entries */
-    tlb_finish_mmu(tlb, start, end);
-
-    /* decrementing rss removed */
-    spin_unlock(&mm->page_table_lock);
-}
-
 
 int direct_unmap(struct mm_struct *mm, unsigned long addr, unsigned long size)
 {
index 33091ac78d219786eace0630105601742994e7e7..79c93767fdcecb45a9fd870aade764c1c5f4eeb5 100644 (file)
@@ -9,7 +9,7 @@
 
 O_TARGET := mm.o
 
-obj-y   := init.o fault.o extable.o pageattr.o hypervisor.o get_unmapped_area.o
+obj-y   := init.o fault.o extable.o pageattr.o hypervisor.o get_unmapped_area.o ioremap.o
 
 export-objs := pageattr.o
 
diff --git a/xenolinux-2.4.21-sparse/arch/xeno/mm/ioremap.c b/xenolinux-2.4.21-sparse/arch/xeno/mm/ioremap.c
new file mode 100644 (file)
index 0000000..f7c6fad
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * arch/xeno/mm/ioremap.c
+ *
+ * Re-map IO memory to kernel address space so that we can access it.
+ *
+ * (C) Copyright 1995 1996 Linus Torvalds
+ *
+ * Modifications for Xenolinux (c) 2003 Keir Fraser
+ */
+
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+#include <asm/uaccess.h>
+#include <asm/tlb.h>
+#include <asm/mmu.h>
+
+#define direct_set_pte(pteptr, pteval) \
+  queue_l1_entry_update(__pa(pteptr)|PGREQ_UNCHECKED_UPDATE, (pteval).pte_low)
+#define direct_pte_clear(pteptr) \
+  queue_l1_entry_update(__pa(pteptr)|PGREQ_UNCHECKED_UPDATE, 0)
+#define __direct_pte(x) ((pte_t) { (x) } )
+#define __direct_mk_pte(page_nr,pgprot) \
+  __direct_pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot))
+#define direct_mk_pte_phys(physpage, pgprot) \
+  __direct_mk_pte((physpage) >> PAGE_SHIFT, pgprot)
+
+
+
+/******************* Mapping a page range directly ************************/
+
+static inline void direct_remap_area_pte(pte_t *pte, 
+                                         unsigned long address, 
+                                         unsigned long size,
+                                         unsigned long machine_addr, 
+                                         pgprot_t prot)
+{
+    unsigned long end;
+
+    address &= ~PMD_MASK;
+    end = address + size;
+    if (end > PMD_SIZE)
+        end = PMD_SIZE;
+    if (address >= end)
+        BUG();
+    do {
+        if (!pte_none(*pte)) {
+            printk("direct_remap_area_pte: page already exists\n");
+            BUG();
+        }
+        direct_set_pte(pte, direct_mk_pte_phys(machine_addr, prot)); 
+        address += PAGE_SIZE;
+        machine_addr += PAGE_SIZE;
+        pte++;
+    } while (address && (address < end));
+}
+
+static inline int direct_remap_area_pmd(struct mm_struct *mm,
+                                        pmd_t *pmd, 
+                                        unsigned long address, 
+                                        unsigned long size,
+                                        unsigned long machine_addr,
+                                        pgprot_t prot)
+{
+    unsigned long end;
+
+    address &= ~PGDIR_MASK;
+    end = address + size;
+    if (end > PGDIR_SIZE)
+        end = PGDIR_SIZE;
+    machine_addr -= address;
+    if (address >= end)
+        BUG();
+    do {
+        pte_t * pte = pte_alloc(mm, pmd, address);
+        if (!pte)
+            return -ENOMEM;
+        direct_remap_area_pte(pte, address, end - address, 
+                              address + machine_addr, prot);
+        address = (address + PMD_SIZE) & PMD_MASK;
+        pmd++;
+    } while (address && (address < end));
+    return 0;
+}
+int direct_remap_area_pages(struct mm_struct *mm,
+                            unsigned long address, 
+                            unsigned long machine_addr,
+                            unsigned long size, 
+                            pgprot_t prot)
+{
+    int error = 0;
+    pgd_t * dir;
+    unsigned long end = address + size;
+
+    machine_addr -= address;
+    dir = pgd_offset(mm, address);
+    flush_cache_all();
+    if (address >= end)
+        BUG();
+    spin_lock(&mm->page_table_lock);
+    do {
+        pmd_t *pmd = pmd_alloc(mm, dir, address);
+        error = -ENOMEM;
+        if (!pmd)
+            break;
+        error = direct_remap_area_pmd(mm, pmd, address, end - address,
+                                      machine_addr + address, prot);
+        if (error)
+            break;
+        address = (address + PGDIR_SIZE) & PGDIR_MASK;
+        dir++;
+    } while (address && (address < end));
+    spin_unlock(&mm->page_table_lock);
+    flush_tlb_all();
+    return error;
+}
+
+
+
+/************************ Zapping a page range directly *******************/
+
+static inline int direct_zap_pte_range(mmu_gather_t *tlb, 
+                                       pmd_t * pmd, 
+                                       unsigned long address, 
+                                       unsigned long size)
+{
+    unsigned long offset;
+    pte_t * ptep;
+    int freed = 0;
+
+    if (pmd_none(*pmd))
+        return 0;
+    if (pmd_bad(*pmd)) {
+        pmd_ERROR(*pmd);
+        pmd_clear(pmd);
+        return 0;
+    }
+    ptep = pte_offset(pmd, address);
+    offset = address & ~PMD_MASK;
+    if (offset + size > PMD_SIZE)
+        size = PMD_SIZE - offset;
+    size &= PAGE_MASK;
+    for (offset=0; offset < size; ptep++, offset += PAGE_SIZE) {
+        pte_t pte = *ptep;
+        if (pte_none(pte))
+            continue;
+        freed++;
+        direct_pte_clear(ptep);
+    }
+
+    return freed;
+}
+
+static inline int direct_zap_pmd_range(mmu_gather_t *tlb, 
+                                       pgd_t * dir, 
+                                       unsigned long address, 
+                                       unsigned long size)
+{
+    pmd_t * pmd;
+    unsigned long end;
+    int freed;
+
+    if (pgd_none(*dir))
+        return 0;
+    if (pgd_bad(*dir)) {
+        pgd_ERROR(*dir);
+        pgd_clear(dir);
+        return 0;
+    }
+    pmd = pmd_offset(dir, address);
+    end = address + size;
+    if (end > ((address + PGDIR_SIZE) & PGDIR_MASK))
+        end = ((address + PGDIR_SIZE) & PGDIR_MASK);
+    freed = 0;
+    do {
+        freed += direct_zap_pte_range(tlb, pmd, address, end - address);
+        address = (address + PMD_SIZE) & PMD_MASK; 
+        pmd++;
+    } while (address < end);
+    return freed;
+}
+
+void direct_zap_page_range(struct mm_struct *mm, 
+                           unsigned long address, 
+                           unsigned long size)
+{
+    mmu_gather_t *tlb;
+    pgd_t * dir;
+    unsigned long start = address, end = address + size;
+    int freed = 0;
+
+    dir = pgd_offset(mm, address);
+
+    if (address >= end)
+        BUG();
+    spin_lock(&mm->page_table_lock);
+    flush_cache_range(mm, address, end);
+    tlb = tlb_gather_mmu(mm);
+
+    do {
+        freed += direct_zap_pmd_range(tlb, dir, address, end - address);
+        address = (address + PGDIR_SIZE) & PGDIR_MASK;
+        dir++;
+    } while (address && (address < end));
+
+    /* this will flush any remaining tlb entries */
+    tlb_finish_mmu(tlb, start, end);
+
+    /* decrementing rss removed */
+    spin_unlock(&mm->page_table_lock);
+}
+
+
+
+/****************** Generic public functions ****************************/
+
+/*
+ * Remap an arbitrary machine address space into the kernel virtual
+ * address space. Needed when a privileged instance of Xenolinux wants
+ * to access space outside its world directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+void * __ioremap(unsigned long machine_addr, 
+                 unsigned long size, 
+                 unsigned long flags)
+{
+    void * addr;
+    struct vm_struct * area;
+    unsigned long offset, last_addr;
+    pgprot_t prot;
+
+    /* Only privileged Xenolinux can make unchecked pagetable updates. */
+    if ( !(start_info.flags & SIF_PRIVILEGED) )
+        return NULL;
+
+    /* Don't allow wraparound or zero size */
+    last_addr = machine_addr + size - 1;
+    if (!size || last_addr < machine_addr)
+        return NULL;
+
+    /* Mappings have to be page-aligned */
+    offset = machine_addr & ~PAGE_MASK;
+    machine_addr &= PAGE_MASK;
+    size = PAGE_ALIGN(last_addr) - machine_addr;
+
+    /* Ok, go for it */
+    area = get_vm_area(size, VM_IOREMAP);
+    if (!area)
+        return NULL;
+    addr = area->addr;
+    prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | 
+                    flags);
+    if (direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(addr), 
+                                machine_addr, size, prot)) {
+        vfree(addr);
+        return NULL;
+    }
+    return (void *) (offset + (char *)addr);
+}
+
+/*
+ * 'vfree' is basically inlined here. This is because we use a different
+ * function to zap the associated page range.
+ */
+void iounmap(void *addr)
+{
+    struct vm_struct **p, *tmp;
+
+    addr = (void *)((unsigned long)addr & PAGE_MASK);
+    
+    if (addr == NULL)
+        return;
+
+    write_lock(&vmlist_lock);
+
+    for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
+        if (tmp->addr == addr) {
+            *p = tmp->next;
+            direct_zap_page_range(&init_mm, 
+                                  VMALLOC_VMADDR(tmp->addr), 
+                                  tmp->size);
+            write_unlock(&vmlist_lock);
+            kfree(tmp);
+            return;
+        }
+    }
+
+    write_unlock(&vmlist_lock);
+    printk(KERN_ERR "Trying to iounmap() nonexistent vm area (%p)\n", addr);
+}
+
+
+#if 0 /* We don't support these functions. They shouldn't be required. */
+void __init *bt_ioremap(unsigned long machine_addr, unsigned long size) {}
+void __init bt_iounmap(void *addr, unsigned long size) {}
+#endif
diff --git a/xenolinux-2.4.21-sparse/include/asm-xeno/io.h b/xenolinux-2.4.21-sparse/include/asm-xeno/io.h
deleted file mode 100644 (file)
index 77a99d1..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-#ifndef _ASM_IO_H
-#define _ASM_IO_H
-
-#include <linux/config.h>
-#include <asm/hypervisor.h>
-/*
- * This file contains the definitions for the x86 IO instructions
- * inb/inw/inl/outb/outw/outl and the "string versions" of the same
- * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
- * versions of the single-IO instructions (inb_p/inw_p/..).
- *
- * This file is not meant to be obfuscating: it's just complicated
- * to (a) handle it all in a way that makes gcc able to optimize it
- * as well as possible and (b) trying to avoid writing the same thing
- * over and over again with slight variations and possibly making a
- * mistake somewhere.
- */
-
-/*
- * Thanks to James van Artsdalen for a better timing-fix than
- * the two short jumps: using outb's to a nonexistent port seems
- * to guarantee better timings even on fast machines.
- *
- * On the other hand, I'd like to be sure of a non-existent port:
- * I feel a bit unsafe about using 0x80 (should be safe, though)
- *
- *             Linus
- */
-
- /*
-  *  Bit simplified and optimized by Jan Hubicka
-  *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999.
-  *
-  *  isa_memset_io, isa_memcpy_fromio, isa_memcpy_toio added,
-  *  isa_read[wl] and isa_write[wl] fixed
-  *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
-  */
-
-#define IO_SPACE_LIMIT 0xffff
-
-#define XQUAD_PORTIO_BASE 0xfe400000
-#define XQUAD_PORTIO_QUAD 0x40000  /* 256k per quad. */
-#define XQUAD_PORTIO_LEN  0x80000  /* Only remapping first 2 quads */
-
-#ifdef __KERNEL__
-
-#include <linux/vmalloc.h>
-
-/*
- * Temporary debugging check to catch old code using
- * unmapped ISA addresses. Will be removed in 2.4.
- */
-#if CONFIG_DEBUG_IOVIRT
-  extern void *__io_virt_debug(unsigned long x, const char *file, int line);
-  extern unsigned long __io_phys_debug(unsigned long x, const char *file, int line);
-  #define __io_virt(x) __io_virt_debug((unsigned long)(x), __FILE__, __LINE__)
-//#define __io_phys(x) __io_phys_debug((unsigned long)(x), __FILE__, __LINE__)
-#else
-  #define __io_virt(x) ((void *)(x))
-//#define __io_phys(x) __pa(x)
-#endif
-
-/**
- *     virt_to_phys    -       map virtual addresses to physical
- *     @address: address to remap
- *
- *     The returned physical address is the physical (CPU) mapping for
- *     the memory address given. It is only valid to use this function on
- *     addresses directly mapped or allocated via kmalloc. 
- *
- *     This function does not give bus mappings for DMA transfers. In
- *     almost all conceivable cases a device driver should not be using
- *     this function
- */
-static inline unsigned long virt_to_phys(volatile void * address)
-{
-       return __pa(address);
-}
-
-/**
- *     phys_to_virt    -       map physical address to virtual
- *     @address: address to remap
- *
- *     The returned virtual address is a current CPU mapping for
- *     the memory address given. It is only valid to use this function on
- *     addresses that have a kernel mapping
- *
- *     This function does not handle bus mappings for DMA transfers. In
- *     almost all conceivable cases a device driver should not be using
- *     this function
- */
-
-static inline void * phys_to_virt(unsigned long address)
-{
-       return __va(address);
-}
-
-/*
- * Change "struct page" to physical address.
- */
-#ifdef CONFIG_HIGHMEM64G
-#define page_to_phys(page)     ((u64)(page - mem_map) << PAGE_SHIFT)
-#else
-#define page_to_phys(page)     ((page - mem_map) << PAGE_SHIFT)
-#endif
-
-/*
- * IO bus memory addresses are also 1:1 with the physical address
- */
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
-#define page_to_bus page_to_phys
-
-/*
- * readX/writeX() are used to access memory mapped devices. On some
- * architectures the memory mapped IO stuff needs to be accessed
- * differently. On the x86 architecture, we just read/write the
- * memory location directly.
- */
-
-#define readb(addr) (*(volatile unsigned char *) __io_virt(addr))
-#define readw(addr) (*(volatile unsigned short *) __io_virt(addr))
-#define readl(addr) (*(volatile unsigned int *) __io_virt(addr))
-#define __raw_readb readb
-#define __raw_readw readw
-#define __raw_readl readl
-
-#define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
-#define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
-#define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))
-#define __raw_writeb writeb
-#define __raw_writew writew
-#define __raw_writel writel
-
-#define memset_io(a,b,c)       __memset(__io_virt(a),(b),(c))
-#define memcpy_fromio(a,b,c)   __memcpy((a),__io_virt(b),(c))
-#define memcpy_toio(a,b,c)     __memcpy(__io_virt(a),(b),(c))
-
-/*
- * ISA space is 'always mapped' on a typical x86 system, no need to
- * explicitly ioremap() it. The fact that the ISA IO space is mapped
- * to PAGE_OFFSET is pure coincidence - it does not mean ISA values
- * are physical addresses. The following constant pointer can be
- * used as the IO-area pointer (it can be iounmapped as well, so the
- * analogy with PCI is quite large):
- */
-#define __ISA_IO_base ((char *)(PAGE_OFFSET))
-
-#define isa_readb(a) readb(__ISA_IO_base + (a))
-#define isa_readw(a) readw(__ISA_IO_base + (a))
-#define isa_readl(a) readl(__ISA_IO_base + (a))
-#define isa_writeb(b,a) writeb(b,__ISA_IO_base + (a))
-#define isa_writew(w,a) writew(w,__ISA_IO_base + (a))
-#define isa_writel(l,a) writel(l,__ISA_IO_base + (a))
-#define isa_memset_io(a,b,c)           memset_io(__ISA_IO_base + (a),(b),(c))
-#define isa_memcpy_fromio(a,b,c)       memcpy_fromio((a),__ISA_IO_base + (b),(c))
-#define isa_memcpy_toio(a,b,c)         memcpy_toio(__ISA_IO_base + (a),(b),(c))
-
-
-/*
- * Again, i386 does not require mem IO specific function.
- */
-
-#define eth_io_copy_and_sum(a,b,c,d)           eth_copy_and_sum((a),__io_virt(b),(c),(d))
-#define isa_eth_io_copy_and_sum(a,b,c,d)       eth_copy_and_sum((a),__io_virt(__ISA_IO_base + (b)),(c),(d))
-
-/**
- *     check_signature         -       find BIOS signatures
- *     @io_addr: mmio address to check 
- *     @signature:  signature block
- *     @length: length of signature
- *
- *     Perform a signature comparison with the mmio address io_addr. This
- *     address should have been obtained by ioremap.
- *     Returns 1 on a match.
- */
-static inline int check_signature(unsigned long io_addr,
-       const unsigned char *signature, int length)
-{
-       int retval = 0;
-       do {
-               if (readb(io_addr) != *signature)
-                       goto out;
-               io_addr++;
-               signature++;
-               length--;
-       } while (length);
-       retval = 1;
-out:
-       return retval;
-}
-
-/**
- *     isa_check_signature             -       find BIOS signatures
- *     @io_addr: mmio address to check 
- *     @signature:  signature block
- *     @length: length of signature
- *
- *     Perform a signature comparison with the ISA mmio address io_addr.
- *     Returns 1 on a match.
- *
- *     This function is deprecated. New drivers should use ioremap and
- *     check_signature.
- */
-
-static inline int isa_check_signature(unsigned long io_addr,
-       const unsigned char *signature, int length)
-{
-       int retval = 0;
-       do {
-               if (isa_readb(io_addr) != *signature)
-                       goto out;
-               io_addr++;
-               signature++;
-               length--;
-       } while (length);
-       retval = 1;
-out:
-       return retval;
-}
-
-/*
- *     Cache management
- *
- *     This needed for two cases
- *     1. Out of order aware processors
- *     2. Accidentally out of order processors (PPro errata #51)
- */
-#if defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE)
-
-static inline void flush_write_buffers(void)
-{
-       __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory");
-}
-
-#define dma_cache_inv(_start,_size)            flush_write_buffers()
-#define dma_cache_wback(_start,_size)          flush_write_buffers()
-#define dma_cache_wback_inv(_start,_size)      flush_write_buffers()
-
-#else
-
-/* Nothing to do */
-
-#define dma_cache_inv(_start,_size)            do { } while (0)
-#define dma_cache_wback(_start,_size)          do { } while (0)
-#define dma_cache_wback_inv(_start,_size)      do { } while (0)
-#define flush_write_buffers()
-
-#endif
-
-#endif /* __KERNEL__ */
-
-#ifdef SLOW_IO_BY_JUMPING
-#define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:"
-#else
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
-#endif
-
-#ifdef REALLY_SLOW_IO
-#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
-#else
-#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO
-#endif
-
-#ifdef CONFIG_MULTIQUAD
-extern void *xquad_portio;    /* Where the IO area was mapped */
-#endif /* CONFIG_MULTIQUAD */
-
-/*
- * Talk about misusing macros..
- */
-#define __OUT1(s,x) \
-static inline void out##s(unsigned x value, unsigned short port) {
-
-#define __OUT2(s,s1,s2) \
-__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
-
-#if defined (CONFIG_MULTIQUAD) && !defined(STANDALONE)
-#define __OUTQ(s,ss,x)    /* Do the equivalent of the portio op on quads */ \
-static inline void out##ss(unsigned x value, unsigned short port) { \
-       if (xquad_portio) \
-               write##s(value, (unsigned long) xquad_portio + port); \
-       else               /* We're still in early boot, running on quad 0 */ \
-               out##ss##_local(value, port); \
-} \
-static inline void out##ss##_quad(unsigned x value, unsigned short port, int quad) { \
-       if (xquad_portio) \
-               write##s(value, (unsigned long) xquad_portio + (XQUAD_PORTIO_QUAD*quad)\
-                       + port); \
-}
-
-#define __INQ(s,ss)       /* Do the equivalent of the portio op on quads */ \
-static inline RETURN_TYPE in##ss(unsigned short port) { \
-       if (xquad_portio) \
-               return read##s((unsigned long) xquad_portio + port); \
-       else               /* We're still in early boot, running on quad 0 */ \
-               return in##ss##_local(port); \
-} \
-static inline RETURN_TYPE in##ss##_quad(unsigned short port, int quad) { \
-       if (xquad_portio) \
-               return read##s((unsigned long) xquad_portio + (XQUAD_PORTIO_QUAD*quad)\
-                       + port); \
-       else\
-               return 0;\
-}
-#endif /* CONFIG_MULTIQUAD && !STANDALONE */
-
-#if !defined(CONFIG_MULTIQUAD) || defined(STANDALONE)
-#define __OUT(s,s1,x) \
-__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \
-__OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} 
-#else
-/* Make the default portio routines operate on quad 0 */
-#define __OUT(s,s1,x) \
-__OUT1(s##_local,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \
-__OUT1(s##_p_local,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} \
-__OUTQ(s,s,x) \
-__OUTQ(s,s##_p,x) 
-#endif /* !CONFIG_MULTIQUAD || STANDALONE */
-
-#define __IN1(s) \
-static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
-
-#define __IN2(s,s1,s2) \
-__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
-
-#if !defined(CONFIG_MULTIQUAD) || defined(STANDALONE)
-#define __IN(s,s1,i...) \
-__IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
-__IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } 
-#else
-/* Make the default portio routines operate on quad 0 */
-#define __IN(s,s1,i...) \
-__IN1(s##_local) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
-__IN1(s##_p_local) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
-__INQ(s,s) \
-__INQ(s,s##_p) 
-#endif /* !CONFIG_MULTIQUAD || STANDALONE */
-
-#define __INS(s) \
-static inline void ins##s(unsigned short port, void * addr, unsigned long count) \
-{ __asm__ __volatile__ ("rep ; ins" #s \
-: "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
-
-#define __OUTS(s) \
-static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
-{ __asm__ __volatile__ ("rep ; outs" #s \
-: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
-
-#define RETURN_TYPE unsigned char
-__IN(b,"")
-#undef RETURN_TYPE
-#define RETURN_TYPE unsigned short
-__IN(w,"")
-#undef RETURN_TYPE
-#define RETURN_TYPE unsigned int
-__IN(l,"")
-#undef RETURN_TYPE
-
-__OUT(b,"b",char)
-__OUT(w,"w",short)
-__OUT(l,,int)
-
-__INS(b)
-__INS(w)
-__INS(l)
-
-__OUTS(b)
-__OUTS(w)
-__OUTS(l)
-
-#endif
index 9e1bb81932dff2e9678835aa00ebce059c707a08..8c02e17f1e7a9c0129292cb89028c0c4a434f421 100755 (executable)
@@ -111,6 +111,7 @@ ln -sf ../asm-i386/hdreg.h
 ln -sf ../asm-i386/i387.h 
 ln -sf ../asm-i386/ide.h 
 ln -sf ../asm-i386/init.h 
+ln -sf ../asm-i386/io.h
 ln -sf ../asm-i386/io_apic.h
 ln -sf ../asm-i386/ioctl.h
 ln -sf ../asm-i386/ioctls.h